package com.hspedu.reflection;

import org.junit.Test;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author DL5O
 * @version 1.0
 * 演示如何通过类的结构信息
 */
public class ReflectionUtils {
    public static void main(String[] args) {

    }

    //第一组API
    //java.lang.Class
    @Test
    public void api01() throws Exception {
        Class<?> cls = Class.forName("com.hspedu.reflection.Person");

        String name = cls.getName();
        System.out.println("全类名:" + name);

        String simpleName = cls.getSimpleName();
        System.out.println("获得简单类名:" + simpleName);

        System.out.println("==============");
        //getFields:获取所有 public 修饰的属性，包含本类以及父类的
        Field[] fields = cls.getFields();
        for (Field field : fields) {
            System.out.println("本类以及父类的public属性=" + field.getName());
        }
        System.out.println("==============");
        //getDeclaredFields:获取本类中所有属性
        Field[] declaredFields = cls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本类所有的属性=" + declaredField.getName());
        }
        System.out.println("==============");

        //getMethods:获取所有 public 修饰的方法，包含本类以及父类的
        Method[] methods = cls.getMethods();
        for (Method method : methods) {
            System.out.println("本类及父类的方法=" + method);
        }
        System.out.println("==============");
        //getDeclaredMethods:获取本类中所有方法
        Method[] declaredMethods = cls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("本类中所有的方法=" + declaredMethod.getName());
        }

        //getConstructors: 获取所有 public 修饰的构造器，包含本类
        Constructor<?>[] constructors = cls.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println("所有public 修饰的构造器=" + constructor.getName());
        }

        //getDeclaredConstructors:获取本类中所有构造器
        Constructor<?>[] declaredConstructors = cls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("本类中的构造器=" + declaredConstructor);
        }

        //getPackage:以Package形式返回 包信息
        System.out.println(cls.getPackage());//得到报名

        //getSuperClass:以Class形式返回父类信息
        Class<?> superclass = cls.getSuperclass();//得到父类的信息
        System.out.println("得到父类的信息=" + superclass);

        //getInterfaces:以 Class[]形式返回接口信息
        Class<?>[] interfaces = cls.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println("接口信息=" + anInterface);
        }

        //getAnnotations:以 Annotation[] 形式返回注解信息
        Annotation[] annotations = cls.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("注解信息=" + annotation);
        }
    }

    //第二API
    //java.lang.reflect.Field
    @Test
    public void api02() throws Exception {
        Class<?> personCls = Class.forName("com.hspedu.reflection.Person");
        //规定 说明:
        // 默认修饰符 是 0 ，
        // public 是 1 ，private 是 2 ，
        // protected 是 4 , static 是 8
        int modifiers = personCls.getModifiers();
        System.out.println("类的修饰符:" + modifiers);

        Field[] fields = personCls.getDeclaredFields();//获取本类所有属性
        for (Field field : fields) {
            System.out.println("访问修饰符:" + field.getModifiers() +
                    " 属性名:" + field.getName() +
                    " 该类的属性:" + field.getType()
            );
        }

    }

    @Test
    //第三组api
    public void api03() throws Exception {
        Class<?> personCls = Class.forName("com.hspedu.reflection.Person");
        //第三组api
        //getDeclaredMethods:获取本类中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.print("访问修饰符:" + declaredMethod.getModifiers() +
                            " 方法名:" + declaredMethod.getName() +
                            " 返回类型:" + declaredMethod.getReturnType()
                            //getReturnType:以class返回类型
            );
            System.out.print(" 参数列表:");
            Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.print(parameterType + " ");
            }
            System.out.println();
        }


    }

    //第四组api
    @Test
    public void api04() throws ClassNotFoundException {
        Class<?> personCls = Class.forName("com.hspedu.reflection.Person");
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.print("构造器: "+ declaredConstructor.getName());
            Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
            System.out.print(" 参数列表:");
            for (Class<?> parameterType : parameterTypes) {
                System.out.print(parameterType.getName() + " ");
            }
            System.out.println();
        }
    }
}



class A {
    public String hobby;

    public void hi() {
        System.out.println("hi");
    }

    public A() {
    }
}

interface IA {

}

interface IE {

}


@Deprecated
class Person extends A implements IA, IE {
    //属性
    public String name;
    protected int age;
    String job;
    private double sal;


    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person(String name, int age, String job) {
        this.name = name;
        this.age = age;
        this.job = job;
    }

    //方法
    public void m1(double b) {
        System.out.println("m1");
    }


    protected String m2(int a,int b,String str) {
        System.out.println("m2");
        return null;
    }

    void m3(char a) {
        System.out.println("m3");
    }

    private void m4() {
        System.out.println("m4");
    }
}